
#include "win32.h"
#include "tcpsocket.h"

namespace tinkle {

TCPSocket::TCPSocket() {

}

TCPSocket::TCPSocket(const std::string &host, const std::string &port) {
    _host = host;
    _port = port;
}

TCPSocket::~TCPSocket() {

}

int TCPSocket::Connect() {
    //Tell the system what kind of address info we want
    struct addrinfo addrCriteria;
    memset(&addrCriteria, 0, sizeof(addrCriteria));
    addrCriteria.ai_family = AF_UNSPEC;        //v4 or v6 is ok
    addrCriteria.ai_socktype = SOCK_STREAM;   //Only stream sockets
    addrCriteria.ai_protocol = IPPROTO_TCP;     //Only TCP protocol
    //Get  address
    struct addrinfo *servAddr;    //Holder for returned list of server address
    int rtnVal = getaddrinfo(_host.c_str(), _port.c_str(), &addrCriteria,
        &servAddr);
    if (rtnVal != 0) {
        //Error handle here
        printf ("Error getaddrinfo, %d %d\n", GetLastError(), rtnVal);
        exit(1);
    }
    //SOCKET sock = SOCKET_ERROR;
    for (struct addrinfo *addr = servAddr; addr; addr = addr->ai_next) {
        _sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (_sock == SOCKET_ERROR) {
            continue;      //Socket creation failed, try next address
        }
        // set socket to nonblocking mode
        u_long ioMode = 1;      // nonzero indicates nonblocking mode
        rtnVal = ioctlsocket(_sock, FIONBIO, &ioMode);
        if (rtnVal != NO_ERROR) {
            printf ("ioctlsocket(): %s\n", GetLastError());
        }
        //Establish the connection
        if (connect(_sock, addr->ai_addr, addr->ai_addrlen) == 0) {
            break;       //Socket connection succeeded;
        }
#ifdef WIN32
        closesocket(_sock);     //Socket connection failed, try next address
#else
        close(_fd);
#endif
        _sock = SOCKET_ERROR;
    }
    freeaddrinfo(servAddr);     //free addrinfo allocated in getaddrinfo()
    return _sock;
}

int TCPSocket::_NonTLSRead(char *buf, int len) {
    return recv(_sock, buf, len, 0);
}

int TCPSocket::_NonTLSWrite(char *buf, int len) {
    return send(_sock, buf, len, 0);
}

}   //namespace tinkle